package com.safetys.co.gateway.v2.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.setting.Setting;
import com.safetys.co.apisix.service.APISixRoutesService;
import com.safetys.co.gateway.entity.Settings;
import com.safetys.co.gateway.v2.entity.ForwardAuth;
import com.safetys.co.gateway.v2.entity.Gateway;
import com.safetys.co.gateway.v2.entity.ProxyRewrite;
import com.safetys.co.gateway.v2.entity.vo.GatewayVO;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class GatewayService {

    APISixRoutesService apiSixRoutesService = null;
    private static GatewayService gatewayService = null;
    private Settings settings = new Settings();

    private GatewayService() {

        super();
        Setting setting = new Setting("APISixHelper.properties");
        log.info(setting.toString());

        settings.setServiceURL(setting.get("apisix.serviceURL"));
        settings.setK(setting.get("apisix.k"));

        com.safetys.co.apisix.entity.Settings _settings = new com.safetys.co.apisix.entity.Settings();
        _settings.setServiceURL(settings.getServiceURL());
        _settings.setK(settings.getK());
        apiSixRoutesService = APISixRoutesService.getInstance(_settings);
    }

    private GatewayService(Settings settings) {

        super();
        this.settings = settings;
        com.safetys.co.apisix.entity.Settings _settings = new com.safetys.co.apisix.entity.Settings();
        _settings.setServiceURL(settings.getServiceURL());
        _settings.setK(settings.getK());
        apiSixRoutesService = APISixRoutesService.getInstance(_settings);
    }

    public Settings getSettings() {
        return settings;
    }

    public static GatewayService getInstance() {

        if (gatewayService == null) {
            HttpGlobalConfig.setTimeout(5000);
            gatewayService = new GatewayService();
        }
        return gatewayService;
    }

    public static GatewayService getInstance(Settings settings) {

        if (gatewayService == null) {
            HttpGlobalConfig.setTimeout(5000);
            gatewayService = new GatewayService(settings);
        }
        return gatewayService;
    }

    private Gateway transGateway(GatewayVO gatewayVO) {

        Gateway gateway = new Gateway();
        String url = gatewayVO.getUri();
        StringBuffer sb = new StringBuffer();
        if (StrUtil.isNotEmpty(url)) {
            sb.append(url);
            url = String.format("/%s/*", sb.toString());
            gateway.setUri(url);
            if (StrUtil.isNotEmpty(gatewayVO.getName())) {
                gateway.setName(gatewayVO.getName());
            } else {
                gateway.setName(sb.toString());
            }
            if (StrUtil.isNotEmpty(gatewayVO.getDesc())){
                gateway.setDesc(gatewayVO.getDesc());
            } else {
                gateway.setDesc(sb.toString());
            }
        } else {
            JSONObject obj = apiSixRoutesService.getResource(gatewayVO.getId());
            JSONObject value = (JSONObject) obj.get("value");
            url = value.getStr("uri");
            url = url.substring(1, url.length() - 2);
            log.info(url);
            sb.append(url);
        }

        if (StrUtil.isNotEmpty(gatewayVO.getType())) {
            gateway.getUpstream().setType(gatewayVO.getType());
        }

        if (gatewayVO.getNodes().size() > 0) {
            gateway.getUpstream().getNodes().putAll(gatewayVO.getNodes());
        }

        ProxyRewrite proxyRewrite = new ProxyRewrite();

        List<String> regex_uri = new ArrayList<>();
        String proxy = String.format("^/%s/(.*)", sb.toString());
        regex_uri.add(proxy);
        regex_uri.add("/$1");
        proxyRewrite.setRegex_uri(regex_uri);
        JSONObject obj01 = JSONUtil.parseObj(proxyRewrite);

        ForwardAuth forwardAuth = new ForwardAuth();
        forwardAuth.setUri(gatewayVO.getAuthUrl());
        forwardAuth.setRequest_method("GET");
        forwardAuth.getRequest_headers().add("Authorization");
        forwardAuth.getRequest_headers().add("Mass-Auth-Token");
        forwardAuth.getRequest_headers().add("Mass-Ai-Service");
        forwardAuth.getUpstream_headers().add("X-User-ID");
        forwardAuth.getUpstream_headers().add("Authorization");
        // application/json
        // forwardAuth.getUpstream_headers().add("Content-Type");
        forwardAuth.getClient_headers().add("Location");
        JSONObject obj02 = JSONUtil.parseObj(forwardAuth);

        JSONObject objs = new JSONObject();
        objs.set("forward-auth", obj02);

        if (gatewayVO.getRewrite()) {
            objs.set("proxy-rewrite", obj01);
        }

        gateway.setPlugins(objs);

        log.info(gateway.toString());
        return gateway;
    }

    public String createGateway(GatewayVO gatewayVO) {

        Gateway gateway = transGateway(gatewayVO);
        String requestBody = gateway.toString();
        StringBuffer sb = new StringBuffer(this.settings.getServiceURL());
        sb.append("/apisix/admin/routes");
        String requestURL = String.format(sb.toString());
        log.info(requestURL);
        log.info(gateway.toString());
        HttpResponse response = ((HttpRequest) HttpUtil.createRequest(Method.POST, requestURL).header("X-API-KEY", this.settings.getK())).contentType(ContentType.JSON.getValue()).body(requestBody).execute();
        log.info(response.body());
        JSONObject ret = JSONUtil.parseObj(response.body());
        String key = ret.get("key").toString();
        key = key.substring(key.indexOf("/apisix/routes/") + "/apisix/routes/".length());
        log.info("status {}", response.getStatus());
        return key;
    }

    public String updateGateway(GatewayVO gatewayVO) {

        Gateway gateway = transGateway(gatewayVO);
        StringBuffer sb = new StringBuffer(this.settings.getServiceURL());
        sb.append("/apisix/admin/routes/%s");
        String requestURL = String.format(sb.toString(), gatewayVO.getId());
        log.info(requestURL);
        String requestBody = gateway.toString();
        log.info(requestBody);
        HttpResponse response = ((HttpRequest) HttpUtil.createRequest(Method.PATCH, requestURL).header("X-API-KEY", this.settings.getK())).contentType(ContentType.JSON.getValue()).body(requestBody).execute();
        log.info(response.body());
        JSONObject ret = JSONUtil.parseObj(response.body());
        String key = ret.get("key").toString();
        key = key.substring(key.indexOf("/apisix/routes/") + "/apisix/routes/".length());
        log.info("status {}", response.getStatus());
        return key;
    }
}
